package edu.hawaii.myisern.model;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.List;
import org.junit.Test;

/**
 * Test the Model.
 * 
 * @author Randy Cox
 * 
 */
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
public class TestModel {

  private final String RTEST_FILE = "c:/data/rtest.xml";
  private final String OTEST_FILE = "c:/data/otest.xml";
  private final String CTEST_FILE = "c:/data/ctest.xml";
  private final String TEST_FILE = "c:/data/test.xml";

  /**
   * Test the insert, update, query etc for the researcher table.
   * 
   */
  @Test
  public void testResearcher() {
    Model model = Model.getInstance();
    model.clearResearchers();

    // Set up test strings.
    String id = ("FIRST_LAST");
    String name = "First Last ";
    String email = "Email";
    String org = "Org";
    String pict = "Pict";
    String bio = "Bio";

    // Set up record vars.
    MyResearcher researcher = new MyResearcher();
    researcher.setName(name);
    researcher.setEmail(email);
    researcher.setOrganization(org);
    researcher.setPictureLink(pict);
    researcher.setBio(bio);

    // Save researcher and check count.
    model.saveResearcher(researcher);

    // Retrieve researcher back and check values.
    MyResearcher researcher2 = model.getResearcher(id);
    assertEquals("Check ID.", id, researcher2.getId());
    assertEquals("Check name.", name.trim(), researcher2.getName());
    assertEquals("Check email.", email, researcher2.getEmail());
    assertEquals("Check organization.", org, researcher2.getOrganization());
    assertEquals("Check pictureLink.", pict, researcher2.getPictureLink());
    assertEquals("Check bio.", bio, researcher2.getBio());

    // Check list function
    List<MyResearcher> results = model.listResearchers();
    int size = 1;
    assertEquals("Check organizations size of list", size, results.size());
    assertEquals("Check organization record 1", id, results.get(0).getId());

    // Delete
    model.deleteResearcher(name);
    results = model.listResearchers();
    size = 0;
    assertEquals("Check organizations size after delete", size, results.size());

    // Export-Import
    model.clearResearchers();
    model.saveResearcher(researcher);
    model.exportResearchers(TEST_FILE);
    model.clearResearchers();
    model.importResearchers(TEST_FILE);
    researcher2 = model.getResearcher(id);
    assertEquals("Check ID.", id, researcher2.getId());
    assertEquals("Check name.", name.trim(), researcher2.getName());
    assertEquals("Check email.", email, researcher2.getEmail());
    assertEquals("Check organization.", org, researcher2.getOrganization());
    assertEquals("Check pictureLink.", pict, researcher2.getPictureLink());
    assertEquals("Check bio.", bio, researcher2.getBio());
  }

  /**
   * Test the insert, update, query etc for the organization table.
   * 
   */
  @Test
  public void testOrganization() {
    Model model = Model.getInstance();
    model.clearOrganizations();

    // Set up test strings.
    String id = ("ORGANIZATION");
    String name = "Organization";
    String type = "Type";
    String contact = "Contact";
    String[] researchers = { "Researcher1", "Researcher2", "Researcher3" };
    String country = "Country";
    String[] keywords = { "Keyword1", "Keyword2", "Keyword3" };
    String description = "Description";
    String homePage = "Home Page";

    // Set up record vars.
    MyOrganization organization = new MyOrganization();
    organization.setName(name);
    organization.setType(type);
    organization.setContact(contact);
    organization.addAffiliatedResearcher(researchers[0]);
    organization.addAffiliatedResearcher(researchers[1]);
    organization.addAffiliatedResearcher(researchers[2]);
    organization.setCountry(country);
    organization.addResearchKeyword(keywords[0]);
    organization.addResearchKeyword(keywords[1]);
    organization.addResearchKeyword(keywords[2]);
    organization.setResearchDescription(description);
    organization.setHomePage(homePage);

    // Save organization and check count.
    model.saveOrganization(organization);

    // Retrieve organization back and check values.
    MyOrganization organization2 = model.getOrganization(id);
    assertEquals("Check ID2.", id, organization2.getId());
    assertEquals("Check name2.", name, organization2.getName());
    assertEquals("Check type2.", type, organization2.getType());
    assertEquals("Check contact2.", contact, organization2.getContact());
    assertEquals("Check res2-1.", researchers[0], organization2.getAffiliatedResearchers().get(0));
    assertEquals("Check res2-2.", researchers[1], organization2.getAffiliatedResearchers().get(1));
    assertEquals("Check res2-3.", researchers[2], organization2.getAffiliatedResearchers().get(2));
    assertEquals("Check country2.", country, organization2.getCountry());
    assertEquals("Check keyword2-1.", keywords[0], organization2.getResearchKeywords().get(0));
    assertEquals("Check keyword2-2.", keywords[1], organization2.getResearchKeywords().get(1));
    assertEquals("Check keyword2-3.", keywords[2], organization2.getResearchKeywords().get(2));
    assertEquals("Check descripiton2.", description, organization2.getResearchDescription());
    assertEquals("Check homepage2.", homePage, organization2.getHomePage());

    // Check list function
    List<MyOrganization> results = model.listOrganizations();
    int size = 1;
    assertEquals("Check organiziatons size of list", size, results.size());
    assertEquals("Check organiziaton record 1", id, results.get(0).getId());

    // Delete
    model.deleteOrganization(name);
    results = model.listOrganizations();
    size = 0;
    assertEquals("Check organizations size after delete", size, results.size());

    // Export-Import
    model.clearOrganizations();
    model.saveOrganization(organization);
    model.exportOrganizations(TEST_FILE);
    model.clearOrganizations();
    model.importOrganizations(TEST_FILE);
    organization2 = model.getOrganization(id);
    assertEquals("Check ID2.", id, organization2.getId());
    assertEquals("Check name2.", name, organization2.getName());
    assertEquals("Check type2.", type, organization2.getType());
    assertEquals("Check contact2.", contact, organization2.getContact());
    assertEquals("Check res2-1.", researchers[0], organization2.getAffiliatedResearchers().get(0));
    assertEquals("Check res2-2.", researchers[1], organization2.getAffiliatedResearchers().get(1));
    assertEquals("Check res2-3.", researchers[2], organization2.getAffiliatedResearchers().get(2));
    assertEquals("Check country2.", country, organization2.getCountry());
    assertEquals("Check keyword2-1.", keywords[0], organization2.getResearchKeywords().get(0));
    assertEquals("Check keyword2-2.", keywords[1], organization2.getResearchKeywords().get(1));
    assertEquals("Check keyword2-3.", keywords[2], organization2.getResearchKeywords().get(2));
    assertEquals("Check descripiton2.", description, organization2.getResearchDescription());
    assertEquals("Check homepage2.", homePage, organization2.getHomePage());
  }

  /**
   * Test the insert, update, query etc for the collaboration table.
   * 
   */
  @Test
  public void testCollaboration() {
    Model model = Model.getInstance();
    model.clearCollaborations();

    // Set up test strings.
    String id = ("COLLABORATION_NAME");
    String name = "collaboration name ";
    String desc = "Desc";
    String[] organizations = { "Organization1", "Organization2", "Organization3" };
    String[] years = { "2000", "2001", "2002" };
    String[] types = { "Type1", "Type2", "Type3" };
    String[] outcomes = { "Outcome1", "Outcome2", "Outcome3" };

    // Set up record vars.
    MyCollaboration collaboration = new MyCollaboration();
    collaboration.setName(name);
    collaboration.setDescription(desc);
    collaboration.addOrganization(organizations[0]);
    collaboration.addOrganization(organizations[1]);
    collaboration.addOrganization(organizations[2]);
    collaboration.addYear(years[0]);
    collaboration.addYear(years[1]);
    collaboration.addYear(years[2]);
    collaboration.addType(types[0]);
    collaboration.addType(types[1]);
    collaboration.addType(types[2]);
    collaboration.addOutcome(outcomes[0]);
    collaboration.addOutcome(outcomes[1]);
    collaboration.addOutcome(outcomes[2]);

    // Save collaboration and check count.
    model.saveCollaboration(collaboration);

    // Retrieve collaboration back and check values.
    MyCollaboration collaboration2 = model.getCollaboration(id);
    assertEquals("Check ID.", id, collaboration2.getId());
    assertEquals("Check name.", name.trim(), collaboration2.getName());
    assertEquals("Check desc.", desc, collaboration2.getDescription());
    assertEquals("Check org1.", organizations[0], collaboration2.getOrganizations().get(0));
    assertEquals("Check org2.", organizations[1], collaboration2.getOrganizations().get(1));
    assertEquals("Check org3.", organizations[2], collaboration2.getOrganizations().get(2));
    assertEquals("Check year1.", years[0], collaboration2.getYears().get(0));
    assertEquals("Check year2.", years[1], collaboration2.getYears().get(1));
    assertEquals("Check year3.", years[2], collaboration2.getYears().get(2));
    assertEquals("Check type1.", types[0], collaboration2.getTypes().get(0));
    assertEquals("Check type2.", types[1], collaboration2.getTypes().get(1));
    assertEquals("Check type3.", types[2], collaboration2.getTypes().get(2));
    assertEquals("Check outcome1.", outcomes[0], collaboration2.getOutcomes().get(0));
    assertEquals("Check outcome2.", outcomes[1], collaboration2.getOutcomes().get(1));
    assertEquals("Check outcome3.", outcomes[2], collaboration2.getOutcomes().get(2));

    // Check list function
    List<MyCollaboration> results = model.listCollaborations();
    int size = 1;
    assertEquals("Check size of collaborations", size, results.size());
    assertEquals("Check collaboration record 1", id, results.get(0).getId());

    // Delete
    model.deleteCollaboration(name);
    results = model.listCollaborations();
    size = 0;
    assertEquals("Check collaboration size after delete", size, results.size());

    // Export-Import
    model.clearCollaborations();
    model.saveCollaboration(collaboration);
    model.exportCollaborations(TEST_FILE);
    model.clearCollaborations();
    model.importCollaborations(TEST_FILE);
    collaboration2 = model.getCollaboration(id);
    assertEquals("Check ID.", id, collaboration2.getId());
    assertEquals("Check name.", name.trim(), collaboration2.getName());
    assertEquals("Check desc.", desc, collaboration2.getDescription());
    assertEquals("Check org1.", organizations[0], collaboration2.getOrganizations().get(0));
    assertEquals("Check org2.", organizations[1], collaboration2.getOrganizations().get(1));
    assertEquals("Check org3.", organizations[2], collaboration2.getOrganizations().get(2));
    assertEquals("Check year1.", years[0], collaboration2.getYears().get(0));
    assertEquals("Check year2.", years[1], collaboration2.getYears().get(1));
    assertEquals("Check year3.", years[2], collaboration2.getYears().get(2));
    assertEquals("Check type1.", types[0], collaboration2.getTypes().get(0));
    assertEquals("Check type2.", types[1], collaboration2.getTypes().get(1));
    assertEquals("Check type3.", types[2], collaboration2.getTypes().get(2));
    assertEquals("Check outcome1.", outcomes[0], collaboration2.getOutcomes().get(0));
    assertEquals("Check outcome2.", outcomes[1], collaboration2.getOutcomes().get(1));
    assertEquals("Check outcome3.", outcomes[2], collaboration2.getOutcomes().get(2));
  }

  /**
   * Check semantic checks.
   * 
   */
  @Test
  public void testSemanticCheck() {
    Model model = Model.getInstance();

    model.clearResearchers();
    String rname = "Researcher";
    String email = "Email";
    String org = "OrganizationX";
    String pict = "Pict";
    String bio = "Bio";
    MyResearcher researcher = new MyResearcher();
    researcher.setName(rname);
    researcher.setEmail(email);
    researcher.setOrganization(org);
    researcher.setPictureLink(pict);
    researcher.setBio(bio);
    model.saveResearcher(researcher);
    model.exportResearchers(RTEST_FILE);

    model.clearOrganizations();
    String oname = "Organization";
    String type = "Type";
    String contact = "Researcher";
    String[] researchers = { "Researcher", "ResearcherX" };
    String country = "Country";
    String[] keywords = { "Keyword1", "Keyword2", "Keyword3" };
    String description = "Description";
    String homePage = "Home Page";
    MyOrganization organization = new MyOrganization();
    organization.setName(oname);
    organization.setType(type);
    organization.setContact(contact);
    organization.addAffiliatedResearcher(researchers[0]);
    organization.addAffiliatedResearcher(researchers[1]);
    organization.setCountry(country);
    organization.addResearchKeyword(keywords[0]);
    organization.addResearchKeyword(keywords[1]);
    organization.addResearchKeyword(keywords[2]);
    organization.setResearchDescription(description);
    organization.setHomePage(homePage);
    model.saveOrganization(organization);
    model.exportOrganizations(OTEST_FILE);

    model.clearCollaborations();
    String cname = "collaboration name ";
    String desc = "Desc";
    String[] organizations = { "Organization", "OrganizationX" };
    String[] years = { "2000", "2001", "2002" };
    String[] types = { "Type1", "Type2", "Type3" };
    String[] outcomes = { "Outcome1", "Outcome2", "Outcome3" };
    MyCollaboration collaboration = new MyCollaboration();
    collaboration.setName(cname);
    collaboration.setDescription(desc);
    collaboration.addOrganization(organizations[0]);
    collaboration.addOrganization(organizations[1]);
    collaboration.addYear(years[0]);
    collaboration.addYear(years[1]);
    collaboration.addYear(years[2]);
    collaboration.addType(types[0]);
    collaboration.addType(types[1]);
    collaboration.addType(types[2]);
    collaboration.addOutcome(outcomes[0]);
    collaboration.addOutcome(outcomes[1]);
    collaboration.addOutcome(outcomes[2]);
    model.saveCollaboration(collaboration);
    model.exportCollaborations(CTEST_FILE);

    List<List<String>> results;

    results = model.researcherCheck();
    assertEquals("Check researcher check()", "OrganizationX", results.get(0).get(2));
    results = model.organizationCheck();
    assertEquals("Check organization check()", "ResearcherX", results.get(0).get(2));
    results = model.collaborationCheck();
    assertEquals("Check collaboration check()", "OrganizationX", results.get(0).get(2));
  }

  /**
   * Test with the real database.
   */
  @Test
  public void testRealDb() {
    Model model = Model.getInstance();
    model.listOrganizations();
    model.listResearchers();
    model.listCollaborations();
    assertNotNull("Test model", model);
  }
}
